package com.kiss.rpc;

import com.kiss.rpc.channelhandler.handler.RpcRequestEncoder;
import com.kiss.rpc.channelhandler.handler.RpcResponseDecoder;
import com.kiss.rpc.enumeration.RequestType;
import com.kiss.rpc.transport.message.RequestPayload;
import com.kiss.rpc.transport.message.RpcRequest;
import com.kiss.rpc.transport.message.RpcResponse;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
public class RpcConsumerOriginCall {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        ReferenceConfig<MyDo> referenceConfig = new ReferenceConfig<>();
        referenceConfig.setInterfaceRef(MyDo.class);

        RequestPayload requestPayload = new RequestPayload();
        requestPayload.setInterfaceName(referenceConfig.getInterfaceRef().getName());
        requestPayload.setMethodName("doSomething");
        requestPayload.setReturnType(String.class);
        requestPayload.setParametersType(new Class[]{String.class});
        requestPayload.setParametersValue(new Object[]{"hello Rpc"});

        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setSerializeType((byte) 1);
        rpcRequest.setRequestId(1);
        rpcRequest.setRequestPayload(requestPayload);
        rpcRequest.setRequestType(RequestType.REQUEST.getId());
        rpcRequest.setCompressType((byte) 1);
        rpcRequest.setTimeStamp(System.currentTimeMillis());


        CompletableFuture<Object> completableFuture = new CompletableFuture<>();
        Bootstrap bootstrap = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        Channel channel = bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) {
                        socketChannel.pipeline()
                                .addLast(new LoggingHandler())
                                .addLast(new RpcRequestEncoder())
                                .addLast(new RpcResponseDecoder())
                                .addLast(new SimpleChannelInboundHandler<>() {
                                    @Override
                                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) {
                                        completableFuture.complete(o);
                                    }
                                });

                    }
                })
                .connect(new InetSocketAddress("127.0.0.1", 8094)).addListener(
                        (ChannelFutureListener) future -> {
                            if (future.isSuccess()) {
                                log.info("与客户端成功连接");
                            }
                        }
                ).sync().channel();


        channel.writeAndFlush(rpcRequest).addListener(
                (ChannelFutureListener) future -> {
                    if (future.isSuccess()) {
                        log.info("请求发送成功");
                    } else {
                        log.info("请求发送失败");
                    }
                }
        );

        Object res = completableFuture.get();
        if (res instanceof RpcResponse) {
            log.info("方法结果为{}", ((RpcResponse) res).getBody());
        }

        group.shutdownGracefully().sync();
    }
}
